package com.xygz.orm;

import com.xygz.orm.*;
import com.xygz.orm.constants.ORMConstants;
import com.xygz.orm.exception.ColumnException;
import com.xygz.orm.exception.ORMException;
import com.xygz.orm.internal.Select;
import com.xygz.orm.table.ZTableField;
import com.xygz.orm.utils.S;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 *
 * the description for class __Selector
 *
 * @author xiyuan-lgz 2025-09-19 @version v1.0.0 新建与整理
 */
public abstract class Selector<E> extends ConditionWrapper<E, Selector<E>> implements Select<E, Selector<E>>, ORMConstants {
    
    protected Selector(Class<E> rawType) throws ORMException {
        super(rawType);
    }
    
    protected Selector(E en) throws ORMException {
        super(en);
    }
    
    /**
     * 创建 select 查询器
     *
     * @param clz 类
     * @param <E> 表类型
     * @return 查询器对象
     */
    public static <E> Selector<E> of(Class<E> clz) {
        Class<?> c = Selector.class;
        return create((Class<Selector<E>>) c, clz);
    }
    
    /**
     * 创建 select 查询器
     *
     * @param en  类
     * @param <E> 表类型
     * @return 查询器对象
     */
    public static <E> Selector<E> of(E en) {
        Class<?> c = Selector.class;
        return create((Class<Selector<E>>) c, en);
    }
    
    
    /**
     * 指定查询字段
     * <p>
     * 该方法需要与数据库字段名一致
     *
     * @param columns 数据库列名
     * @return 当前查询器
     */
    public abstract <C extends Selector<E>> C select(String column, String... columns);
    
    /**
     * 查询全部字段
     *
     * @param <C>
     * @return
     */
    public abstract <C extends Selector<E>> C selectAll();
    
    /**
     * 查询字段，自定义筛选，
     *
     * <pre>
     * 注：指定了字段查询后，自定义判断条件返回true 的字段失效
     * 例如：
     *   sel.select(Tab::getColumn1);
     *   sel.select((col)->{
     *     if(field.getColumn().equals("column1")) return false; // 排除这个字段的查询， 这里将失效，
     *   })
     * </pre>
     *
     * @param predicate 自定义判断条件
     * @param <C>
     * @return
     */
    public abstract <C extends Selector<E>> C select(Predicate<ZTableField> predicate);
    
    /**
     * 指定字段查询
     *
     * @param column  数据库列名
     * @param columns 数据库列名
     * @return 当前查询器
     */
    public abstract <C extends Selector<E>> C select(SFunc<E, ?> column, SFunc<E, ?>... columns);
    
    
    /**
     * 指定查询字段
     * <p>
     * 该方法需要与数据库字段名一致
     *
     * @param column  数据库列名
     * @param columns 数据库列名
     * @return 当前查询器
     * @throws ColumnException 当指定 column 与Java 属性不匹配时 异常
     */
    public abstract <C extends Selector<E>> C select(SColumn column, SColumn... columns) throws ColumnException;
    
    // /*******************************************************************/
    // // INNER JOIN
    // /*******************************************************************/
    
    
    /**
     * INNER JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> join(Selector<B> sel, Function<SelectJoiner<B>, SelectJoiner<B>> joiner);
    
    /**
     * INNER JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> join(Selector<B> sel, Consumer<SelectJoiner<B>> joiner);
    
    /**
     * INNER JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> join(Class<B> clz, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return join(Selector.of(clz), joiner);
    }
    
    /**
     * INNER JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> join(Class<B> clz, String tableAlias, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return join(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * INNER JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> join(Class<B> clz, String tableAlias, Consumer<SelectJoiner<B>> joiner) {
        return join(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * INNER JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> join(Class<B> clz, Consumer<SelectJoiner<B>> joiner) {
        return join(Selector.of(clz), joiner);
    }
    
    
    // /*******************************************************************/
    // // LEFT JOIN
    // /*******************************************************************/
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> leftJoin(Selector<B> sel, Function<SelectJoiner<B>, SelectJoiner<B>> joiner);
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> leftJoin(Selector<B> sel, Consumer<SelectJoiner<B>> joiner);
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> leftJoin(Class<B> clz, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return leftJoin(Selector.of(clz), joiner);
    }
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> leftJoin(Class<B> clz, String tableAlias, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return leftJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> leftJoin(Class<B> clz, String tableAlias, Consumer<SelectJoiner<B>> joiner) {
        return leftJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * LEFT JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> leftJoin(Class<B> clz, Consumer<SelectJoiner<B>> joiner) {
        return leftJoin(Selector.of(clz), joiner);
    }
    
    
    // /*******************************************************************/
    // // RIGHT JOIN
    // /*******************************************************************/
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> rightJoin(Selector<B> sel, Function<SelectJoiner<B>, SelectJoiner<B>> joiner);
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> rightJoin(Selector<B> sel, Consumer<SelectJoiner<B>> joiner);
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> rightJoin(Class<B> clz, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return rightJoin(Selector.of(clz), joiner);
    }
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> rightJoin(Class<B> clz, String tableAlias, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return rightJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> rightJoin(Class<B> clz, String tableAlias, Consumer<SelectJoiner<B>> joiner) {
        return rightJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * RIGHT JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> rightJoin(Class<B> clz, Consumer<SelectJoiner<B>> joiner) {
        return rightJoin(Selector.of(clz), joiner);
    }
    
    // /*******************************************************************/
    // // CROSS JOIN
    // /*******************************************************************/
    
    /**
     * CROSS JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> crossJoin(Selector<B> sel, Function<SelectJoiner<B>, SelectJoiner<B>> joiner);
    
    /**
     * CROSS JOIN 联表查询
     *
     * @param sel    查询器
     * @param joiner 连接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public abstract <B> Selector<E> crossJoin(Selector<B> sel, Consumer<SelectJoiner<B>> joiner);
    
    /**
     * CROSS JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> crossJoin(Class<B> clz, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return crossJoin(Selector.of(clz), joiner);
    }
    
    /**
     * CROSS JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> crossJoin(Class<B> clz, String tableAlias, Function<SelectJoiner<B>, SelectJoiner<B>> joiner) {
        return crossJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * CROSS JOIN 联表查询
     *
     * @param clz        表类
     * @param tableAlias 表别名
     * @param joiner     链接器
     * @param <B>        表类型
     * @return 查询器本身
     */
    public <B> Selector<E> crossJoin(Class<B> clz, String tableAlias, Consumer<SelectJoiner<B>> joiner) {
        return crossJoin(Selector.of(clz).as(tableAlias), joiner);
    }
    
    /**
     * xx JOIN 联表查询
     *
     * @param clz    表类
     * @param joiner 链接器
     * @param <B>    表类型
     * @return 查询器本身
     */
    public <B> Selector<E> crossJoin(Class<B> clz, Consumer<SelectJoiner<B>> joiner) {
        return crossJoin(Selector.of(clz), joiner);
    }
//
//    /**
//     * 多表联查 on条件，
//     * <pre>
//     * 如果 join 超过 3张表 时 需要指定 表名.属性名 方式.
//     * 例如：selector.on("tab1.col1", "tab2.col1")
//     * </pre>
//     * @param lCol              左表左列, 如果 join 超过 3张表 时 需要指定 表名.属性名 方式，例如：tab1.col1
//     * @param rCol              右表右列, 如果 join 超过 3张表 时 需要指定 表名.属性名 方式，例如：tab2.col2
//     * @return 联表查询器
//     */
//    public abstract Selector<E> on(String lCol, String rCol);
    
    // /*******************************************************************/
    // // count
    // /*******************************************************************/
    //
    // /*******************************************************************/
    // // sum
    // /*******************************************************************/
    //
    // /*******************************************************************/
    // // group by
    // /*******************************************************************/
    //
    // /*******************************************************************/
    // // having
    // /*******************************************************************/
    //
    // /*******************************************************************/
    // // case when then
    // /*******************************************************************/
    
    /**
     * 列编辑器
     */
    public final Selector.ColumnBuilder<E> columnBuilder() {
        return new Selector.ColumnBuilder<E>(this);
    }
    
    /**
     * 判断是否有 orderBy
     */
    public abstract boolean hasOrderBy();
    
    // /**
    //  * 查询一项
    //  *
    //  * @return 数据对象
    //  * @throws ORMException 框架异常
    //  * @throws SQLException 数据库异常
    //  */
    // public E one() throws ORMException, SQLException {
    //     return null;
    // }
    //
    // /**
    //  * 指定结果类型查询一项
    //  *
    //  * @return 数据对象
    //  * @throws ORMException 框架异常
    //  * @throws SQLException 数据库异常
    //  */
    // public <VO> VO one(Class<VO> cls) throws ORMException, SQLException {
    //     return null;
    // }
    
    
    public static class ColumnBuilder<T> {
        
        private Selector<T> selector;
        
        protected ColumnBuilder(Selector<T> selector) {
            this.selector = selector;
        }
        
        public Selector.ColumnBuilder<T> select(String col) {
            return select(col, (String) null);
        }
        
        public Selector.ColumnBuilder<T> select(String col, String as) {
            selector.select(new SColumn(col).as(S.trimToNull(as)));
            return this;
        }
        
        public <A> Selector.ColumnBuilder<T> select(String col, SFunc<A, ?> as) {
            selector.select(new SColumn(col).as(as));
            return this;
        }
        
        public Selector.ColumnBuilder<T> select(SFunc<T, ?> col) {
            return select(col, (String) null);
        }
        
        public Selector.ColumnBuilder<T> select(SFunc<T, ?> col, String as) {
            selector.select(new SColumn(col).as(S.trimToNull(as)));
            return this;
        }
        
        public <A> Selector.ColumnBuilder<T> select(SFunc<T, ?> col, SFunc<A, ?> as) {
            selector.select(new SColumn(col).as(as));
            return this;
        }
        
        public Selector<T> end() {
            return selector;
        }
        
        
    }
    
}
